#include "usbh_core.h"
#include "usbh_cdc_acm.h"
#include <freertos/timers.h>
#include "../HAL/HAL.h"
#include "../public.h"
#include "msg_deal.h"


USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t cdc_read_buf[512];
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t cdc_write_buf[512];

static TimerHandle_t inquire_handle1;
static uint8_t inquire_nums = 0;


const uint8_t response_head[] = {0x77,0xBB};
const uint8_t req_key[] = {0x77,0xAA,0x02,0x00,0x08,0x00,0x0C,0x37};


static int usbh_bulk_send(struct usbh_cdc_acm *cdc_acm_class,uint8_t* buff,uint32_t buff_len)
{
    int ret;
    usbh_bulk_urb_fill(&cdc_acm_class->bulkout_urb, cdc_acm_class->hport, cdc_acm_class->bulkout, buff, buff_len, 3000, NULL, NULL);
    ret = usbh_submit_urb(&cdc_acm_class->bulkout_urb);
    if (ret < 0) 
    {
        USB_LOG_RAW("bulk out error,ret:%d\r\n", ret);
        return -1;
    } else 
    {
        USB_LOG_RAW("send over:%d\r\n", cdc_acm_class->bulkout_urb.actual_length);
    }
    return 0;
}

void usbh_cdc_acm_callback(void *arg, int nbytes)
{
    //struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)arg;
    if (nbytes > 0) {
        for (size_t i = 0; i < nbytes; i++) {
            USB_LOG_RAW("0x%02x ", cdc_read_buf[i]);
        }
        // USB_LOG_RAW("str:%s\r\n", cdc_read_buf);
    }
}


static void usbh_cdc_acm_recv(void *argument)
{
    int ret;
    struct usbh_cdc_acm *cdc_acm_class;
    USB_LOG_RAW("!!!!!!find /dev/ttyACM0\r\n");
    while (1)
    {
        cdc_acm_class = (struct usbh_cdc_acm *)usbh_find_class_instance("/dev/ttyACM0");
        if(cdc_acm_class == NULL)
        {
            break;
        }
        usbh_bulk_urb_fill(&cdc_acm_class->bulkin_urb, cdc_acm_class->hport, cdc_acm_class->bulkin, cdc_read_buf, cdc_acm_class->bulkin->wMaxPacketSize, USB_OSAL_WAITING_FOREVER, usbh_cdc_acm_callback, cdc_acm_class);
        ret = usbh_submit_urb(&cdc_acm_class->bulkin_urb);

        USB_LOG_RAW("ret:%d\r\n",ret);
        if (ret < 0) {
            
        }else
        {
            usb_cache_recv_data(cdc_read_buf,cdc_acm_class->bulkin_urb.actual_length);
        }

    }
    usb_osal_thread_delete(NULL);
}

static void usbh_cdc_acm_deal(void *argument)
{
    int ret;
    struct usbh_cdc_acm *cdc_acm_class;
    uint8_t pass = false;
    
    while (1)
    {
        cdc_acm_class = (struct usbh_cdc_acm *)usbh_find_class_instance("/dev/ttyACM0");
        if(cdc_acm_class == NULL)
        {
            break;
        }
        usb_recv_process(usbh_recv_msg_deal,response_head,sizeof(response_head));
        
        vTaskDelay(10);
    }
    usb_osal_thread_delete(NULL);
}



void inquire_device_key(TimerHandle_t xTimer)
{
    struct usbh_cdc_acm *cdc_acm_class= (struct usbh_cdc_acm *)pvTimerGetTimerID(xTimer);
    inquire_nums++;
    if(inquire_nums >= 3 || true == get_usbd_reply_state())
    {
        xTimerStop(xTimer, 0);
    }else
    {
        memcpy(cdc_write_buf, req_key, sizeof(req_key));
        usbh_bulk_urb_fill(&cdc_acm_class->bulkout_urb, cdc_acm_class->hport, cdc_acm_class->bulkout, cdc_write_buf, sizeof(req_key), 100, NULL, NULL);// 单位ms < 300
        usbh_submit_urb(&cdc_acm_class->bulkout_urb);
    }
}

void usbh_cdc_acm_run(struct usbh_cdc_acm *cdc_acm_class)
{
    inquire_nums = 0;
    usbh_connect_init();
    inquire_handle1 = xTimerCreate((const char *)"inquire_finger", pdMS_TO_TICKS(1000), (UBaseType_t)pdTRUE, (void *const)cdc_acm_class, (TimerCallbackFunction_t)inquire_device_key);
    if (inquire_handle1 == NULL) {
        USB_LOG_ERR("timer creation failed! \r\n");
    }
    usb_osal_thread_create("usbh_cdc_recv", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_acm_recv, NULL);
    usb_osal_thread_create("usbh_cdc_deal", 1024*10, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_acm_deal, NULL);
    xTimerStart(inquire_handle1, 0);
    
}

void usbh_cdc_acm_stop(struct usbh_cdc_acm *cdc_acm_class)
{
    usbh_disconnect_deinit();
}





